home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / TARFILE.GZ / tarfile / ch_5.3 / fitpolyg / fitpolyg.c < prev    next >
C/C++ Source or Header  |  1999-09-11  |  9KB  |  289 lines

  1. /*
  2.  * fitpolyg.c
  3.  *
  4.  * Practical Algorithms for Image Analysis
  5.  *
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* FITPOLYG:    program performs polygonal fit upon image lines, where
  10.  *            input is in PCC code
  11.  *            usage: fitpolyg infile outimg [-t THRESHOLD] [-c] [-w file] [-L]
  12.  */
  13.  
  14. #define THRESH_DFLT 5
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <images.h>
  19. #include <string.h>
  20. #include "tiffimage.h"
  21. #include "pcc2.h"               /* for PCC programs */
  22. extern void print_sos_lic ();
  23.  
  24. unsigned char *fcCode;          /* code storage */
  25. long nByteCode;                 /* no. bytes in code storage */
  26.  
  27. long xytoline (struct point *, long *, long *, long *);
  28. long usage (short);
  29. long input (int, char **, long *, short *, char *);
  30. float slope (int x1, int y1, int x2, int y2);
  31.  
  32. main (argc, argv)
  33.      int argc;
  34.      char *argv[];
  35. {
  36.   Image *imgO;                  /* pointer to output image structure */
  37.   unsigned char **image;        /* output image array */
  38.   long width, height;           /* image size */
  39.   struct point imgSize;         /* image size */
  40.   long thresh;                  /* threshold for fit */
  41.   short coordFlag;              /* flag = 1, print fit coord.s; or 0 */
  42.   struct point *data;           /* data curve */
  43.   long nData;                   /* no. coords in data curve */
  44.   long nSegments;               /* number of segments found */
  45.   long nStructs;                /* number of line structures found */
  46.   long kLine;                   /* line number */
  47.   long lengthSqr, area;         /* length sqr.ed and area of line fits */
  48.   long deltaX, deltaY;          /* x and y increments for line fits */
  49.   long drawline8 ();            /* joins points in 8-connected lines */
  50.   long nFits;                   /* number of polygonal fits */
  51.   struct point pt0, pt1;        /* points to connect fits between */
  52.   long x, y;
  53.   long i;
  54.   char segfile[256];
  55.   int segfileFlag = 0;
  56.   FILE *segstream;
  57.  
  58.   segfile[0] = '\0';
  59. /* user input */
  60.   if (input (argc, argv, &thresh, &coordFlag, segfile) < 0)
  61.     return (-1);
  62.  
  63.   if (strlen (segfile)) {
  64.     segfileFlag = 1;
  65.     segstream = fopen (segfile, "w+");
  66.     fprintf (segstream, "                            \n");  /* write blanks for later fseek */
  67.   }
  68.  
  69. /* open input PCC file */
  70.   if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
  71.     exit (1);
  72.   if (!coordFlag)
  73.     printf ("image size: %dx%d, PCC length = %d\n", width, height, nByteCode);
  74.   imgSize.x = width;
  75.   imgSize.y = height;
  76.  
  77. /* allocate space for data coordinate array */
  78.   if ((data = (struct point *)
  79.        calloc (nByteCode * MAXPERCODE, sizeof (long))) == NULL) {
  80.     printf ("FITPOLYG: not enough memory -- sorry");
  81.     return (-1);
  82.   }
  83.  
  84. /* construct tables of feature chain decodes */
  85.   pccdecodes ();
  86.  
  87. /* perform feature chain decoding */
  88.   pcc2xy (data, &nData);
  89.  
  90.   data[nData++].x = -STOPCODE;
  91.   if ((data = (struct point *)
  92.        realloc (data, nData * sizeof (struct point))) == NULL) {
  93.     printf ("FITPOLYG: not enough memory -- sorry");
  94.     return (-2);
  95.   }
  96.  
  97. /* find x,y coordinates for each line */
  98.   if (xytoline (data, &nData, &nSegments, &nStructs) < 0)
  99.     return (-1);
  100.  
  101. /* allocate output image */
  102.   imgO = ImageAlloc (height, width, 8);
  103.   image = ImageGetPtr (imgO);
  104.  
  105. /* initialize image */
  106.   for (y = 0; y < height; y++)
  107.     for (x = 0; x < width; x++)
  108.       image[y][x] = 255;
  109.  
  110. /* determine polygonal fits */
  111.   kLine = 0;
  112.   for (i = 0, nFits = 0; i < nData; i++) {
  113.     if (data[i].x != -1) {
  114.       pt0.x = data[i].x;
  115.       pt0.y = data[i].y;
  116.       i++;
  117.       if (data[i].x < 0) {      /* one pixel line */
  118.         image[pt0.y][pt0.x] = 255;
  119.         if (coordFlag != 0)
  120.           printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt0.x, pt0.y, kLine);
  121.         if (segfileFlag)
  122.           fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
  123.                    nFits, pt0.x, pt0.y, pt0.x, pt0.y,
  124.                    slope (pt0.x, pt0.y, pt0.x, pt0.y), kLine);
  125.         nFits++;
  126.         kLine++;
  127.       }
  128.       lengthSqr = area = 0;
  129.       while (data[i].x >= 0) {
  130.         x = data[i].x - pt0.x;
  131.         y = data[i].y - pt0.y;
  132.         deltaX = data[i].x - data[i - 1].x;
  133.         deltaY = data[i].y - data[i - 1].y;
  134.         lengthSqr += 2 * (x * deltaX + y * deltaY)
  135.           + deltaX * deltaX + deltaY * deltaY;
  136.         area += x * deltaY - y * deltaX;
  137.         if ((area * area) > (thresh * lengthSqr)) {
  138.           pt1.x = data[i].x;
  139.           pt1.y = data[i].y;
  140.           drawline8 (image, imgSize, pt0, pt1, 0);
  141.           if (coordFlag != 0)
  142.             printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt1.x, pt1.y, kLine);
  143.           if (segfileFlag)
  144.             fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
  145.                      nFits, pt0.x, pt0.y, pt1.x, pt1.y,
  146.                      slope (pt0.x, pt0.y, pt1.x, pt1.y), kLine);
  147.           nFits++;
  148.           pt0.x = data[i].x;
  149.           pt0.y = data[i].y;
  150.           lengthSqr = area = 0;
  151.         }
  152.         i++;
  153.       }
  154.       if (lengthSqr > 0) {
  155.         pt1.x = data[i - 1].x;
  156.         pt1.y = data[i - 1].y;
  157.         drawline8 (image, imgSize, pt0, pt1, 0);
  158.         if (coordFlag != 0)
  159.           printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt1.x, pt1.y, kLine);
  160.         if (segfileFlag)
  161.           fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
  162.                    nFits, pt0.x, pt0.y, pt1.x, pt1.y,
  163.                    slope (pt0.x, pt0.y, pt1.x, pt1.y), kLine);
  164.         nFits++;
  165.       }
  166.       kLine++;
  167.       --i;
  168.     }
  169.   }
  170.  
  171.   if (!coordFlag)
  172.     printf ("Number of segments fit to data = %d.\n", nFits);
  173.  
  174.   if (segfileFlag) {
  175.     fseek (segstream, 0L, SEEK_SET);
  176.     fprintf (segstream, "%d %d %d", nFits, width, height);
  177.     fclose (segstream);
  178.   }
  179. /* write image output file */
  180.   ImageOut (argv[2], imgO);
  181.  
  182.   return (0);
  183. }
  184.  
  185.  
  186.  
  187. /* USAGE:       function gives instructions on usage of program
  188.  *                    usage: usage (flag)
  189.  *              When flag is 1, the long message is given, 0 gives short.
  190.  */
  191.  
  192. long
  193. usage (flag)
  194.      short flag;                /* flag =1 for long message; =0 for short message */
  195. {
  196.  
  197. /* print short usage message or long */
  198.   printf ("USAGE: fitpolyg infile outimg [-t THRESHOLD] [-c] [-w file] [-L]\n");
  199.   if (flag == 0)
  200.     return (-1);
  201.  
  202.   printf ("\nfitpolyg performs polygonal line fitting to image\n");
  203.   printf ("lines; straight line fits are made to portions of each segment\n");
  204.   printf ("to best approximate the chain of points comprising the segment;\n");
  205.   printf ("a segment is a chain of points between features, either\n");
  206.   printf ("endpoint features or junction features.\n\n");
  207.   printf ("ARGUMENTS:\n");
  208.   printf ("    infile: input filename (PCC)\n");
  209.   printf ("    outimg: output image filename (TIF)\n\n");
  210.   printf ("OPTIONS:\n");
  211.   printf ("  -t THRESH: threshold on error for polygonal fit (default = %d);\n", THRESH_DFLT);
  212.   printf ("             the smaller is this threshold, the closer will be the\n");
  213.   printf ("             polygonal fit to the original data, but the more straight\n");
  214.   printf ("             line fit segments will be required.\n");
  215.   printf ("         -c: when set, prints out the (x,y) coordinates of the\n");
  216.   printf ("             polygonal fit endlines.\n");
  217.   printf ("    -w file: save line segment data to a file(.seg) for analysis by xsgll\n");
  218.   printf ("         -L: print Software License for this module\n");
  219.  
  220.   return (-1);
  221. }
  222.  
  223.  
  224. /* INPUT:       function reads input parameters
  225.  *                  usage: input (argc, argv, &thresh, &coordFlag)
  226.  */
  227.  
  228. #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
  229.  
  230. long
  231. input (argc, argv, thresh, coordFlag, segfile)
  232.      int argc;
  233.      char *argv[];
  234.      long *thresh;              /* threshold on polygonal fit */
  235.      short *coordFlag;          /* flag = 1, print coordinates of fit; or 0 */
  236.      char *segfile;             /* filename for saving segment data */
  237. {
  238.   long n;
  239.  
  240.   if (argc == 1)
  241.     USAGE_EXIT (1);
  242.   if (argc == 2)
  243.     USAGE_EXIT (0);
  244.  
  245.   *thresh = THRESH_DFLT;
  246.   *coordFlag = 0;
  247.  
  248.   for (n = 3; n < argc; n++) {
  249.     if (strcmp (argv[n], "-t") == 0) {
  250.       if (++n == argc)
  251.         usage (0);
  252.       *thresh = (long) atol (argv[n]);
  253.     }
  254.     if (strcmp (argv[n], "-w") == 0) {
  255.       if (++n == argc)
  256.         usage (0);
  257.       strcpy (segfile, argv[n]);
  258.     }
  259.     else if (strcmp (argv[n], "-c") == 0)
  260.       *coordFlag = 1;
  261.     else if (strcmp (argv[n], "-L") == 0) {
  262.       print_sos_lic ();
  263.       exit (0);
  264.     }
  265.     else
  266.       USAGE_EXIT (0);
  267.   }
  268.  
  269.  
  270.   return (0);
  271. }
  272.  
  273. float
  274. slope (int x1, int y1, int x2, int y2)
  275. {
  276.   float m;
  277.  
  278.   if ((x2 - x1) == 0) {
  279.     if (y2 - y1 == 0)
  280.       m = (float) 0.0;
  281.     else
  282.       m = (float) 512.0;        /* slope = 512/1 */
  283.   }
  284.   else
  285.     m = ((float) (y2 - y1)) / ((float) (x2 - x1));
  286.  
  287.   return (m);
  288. }
  289.